package com.haidao.admin.component.service.thirdpart.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import com.haidao.admin.common.utils.Base64Util;
import com.haidao.admin.component.configuration.CryptoConfiguration;
import com.haidao.admin.component.constants.Constant;
import com.haidao.admin.component.dao.KeyCodeDao;
import com.haidao.admin.component.entity.KeyCodeInfo;
import com.haidao.admin.component.service.thirdpart.SignatureService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 吉大 HMAC_SM3签名服务类
 */
@Service
@RequiredArgsConstructor
public class SecondAreaSignatureServiceImpl implements SignatureService {
    private static KeyCodeInfo __macKey;  // 加解密密钥

    private final CryptoConfiguration cryptoConfig;

    private final KeyCodeDao keyCodeDao;
    private final JiDaUtilService jiDaUtilService;

    @Override
    public String signature(String str) {
        String keyCode = getKeyCode();
        String hmacUrl = cryptoConfig.getBaseUrl() + cryptoConfig.getHmacUri();

        Map<String, String> reqHeaders = jiDaUtilService.getReqHeaders();
        HashMap<String, Object> reqBody = new HashMap<>();
        reqBody.put("keyCode", keyCode);
        reqBody.put("algorithmParam", "HMAC_SM3");
        reqBody.put("data", Base64Util.encode(str));

        JSONObject respBody = jiDaUtilService.sendPostReq(reqHeaders, reqBody, hmacUrl);
        JSONObject data = respBody.getJSONObject("data");
        return data.getStr("hmac");
    }

    @Override
    public boolean verify(String str, String signature) {
        String signature1 = this.signature(str);
        return signature.equals(signature1);
    }

    /**
     * 获取密钥
     *
     * @return 密钥
     */
    private String getKeyCode() {
        // 0. 内存中存在密钥且未过期则直接返回
        if (__macKey != null && __macKey.getExpirationTime().after(new Date())) {
            return __macKey.getKeyCode();
        }
        // 1.数据库获取密钥
        KeyCodeInfo dbKeyCodeInfo = keyCodeDao.findByUsage(Constant.MAC);
        if (dbKeyCodeInfo == null) {
            // 2.1.1 没有密钥则从密钥服务器获取密钥
            dbKeyCodeInfo = jiDaUtilService.getKeyCodeFromServer("SM4", 128, "1");
            dbKeyCodeInfo.setUsage(Constant.MAC);
            // 2.1.2保存密钥到数据库
            keyCodeDao.save(dbKeyCodeInfo);
            // 2.1.3保存密钥到内存
            __macKey = dbKeyCodeInfo;
            return __macKey.getKeyCode();
        }
        // 2.2.1存在秘钥
        __macKey = dbKeyCodeInfo;
        Date expirationTime = __macKey.getExpirationTime();
        int compare = DateUtil.compare(expirationTime, new Date());
        // 2.2.2判断是否过期
        if (compare <= 0) {
            // 2.2.3过期则从密钥服务器延长密钥
            __macKey = jiDaUtilService.extendKeyCodeExpirationTime(__macKey);
            // 2.2.4更新密钥到数据库
            keyCodeDao.save(__macKey);  // 对象存在id时自动更新
        }
        // 3返回密钥
        return __macKey.getKeyCode();
    }

}
